
package jogs.net; 

import jogs.core.GameServerInstance;
import jogs.core.InvalidSettingsException;

import java.net.*;
import java.util.ArrayList; 

/**
 * A TCP Game Server is a TCP server dedicated to playing a single 
 * particular game instance (eg Tic Tac Toe). A TCP Game Server is
 * created by the Game Room Server when a game is created. 
 * The TCP Game Server is assigned a particular game, which must 
 * implement jogs.core.GameServerInstance
 */

public class TCPGameServer
{
  private int port; 
  private String gameNameTag; 
  private String gameSettings;

  private GameServerInstance theGameServer; 
  private ServerSocket socket; 
  
  private ArrayList<TCPClientHandler> clientHandlers; 

  public TCPGameServer(int _port, String _gameNameTag, String _gameSettings)
  {
    port = _port; 
    gameNameTag = _gameNameTag; 
    gameSettings = _gameSettings; 
    theGameServer = null; 
    clientHandlers = new ArrayList<TCPClientHandler>();
  }

  public static void main(String[] args)
  {
    // expects command-line args: <game nametag> <game settings string>
    if (args.length != 3)
    {
      System.err.println("Usage: TCPGameServer <port> <game nametag> <game settings string>");
      System.exit(-1);
    }

    TCPGameServer tgs = new TCPGameServer(Integer.parseInt(args[0]), args[1], args[2]); 
    tgs.run();
  }

  private void loadGame()
  {
  }

  private void parseSettings()
  {
    try 
    {
      theGameServer.parseSettings(gameSettings); 
    }
    catch (InvalidSettingsException e)
    {
      System.err.println("Caught InvalidSettingsException: " + e.toString());
      e.printStackTrace(); 
      System.exit(-1);
    }
  }
  
  private void run()
  {
    int id = 0; 
    
    loadGame(); 
    parseSettings();  

    // Game loaded properly and settings parsed OK. Load the server! 
    try 
    { 
      socket = new ServerSocket(port); 

      // Now we need to accept connection and start client handlers

      while (true)
      {
        Socket clientSocket = socket.accept(); 
        
        // Accept all connections then check if game allows them in
        
        id++;
        TCPClientHandler tch = new TCPClientHandler(clientSocket, id, this);
        
        clientHandlers.add(tch); 
        
        tch.start();
      }
    }
    catch(Exception e)
    {
      e.printStackTrace(); 
    }
  }
  
  protected void handleMessage(int clientId, String line)
  {
    // If it starts with the game message prefix, let the game handle it
    if (line.startsWith(Constants.GAMEMSGPREF))
      theGameServer.handleMessage(clientId, line); 
    else
    {
      // Otherwise it is a message to the tcp server itself so handle it separately
      // ...
    }
  }
  
  // These are to be called by the game instances
  
  public void send(int id, String message)
  {
    TCPClientHandler ch = clientHandlers.get(id); 
    ch.send(message); 
  }
  
  public void broadcast(String msg)
  {
    for (TCPClientHandler ch : clientHandlers)
    {
      if (!ch.isDisconnected())
      {    
        ch.send(msg);
      }
    }
  }
}

